《逆向工程核心原理》学习笔记(四):API钩取 您所在的位置:网站首页 iat hook原理 《逆向工程核心原理》学习笔记(四):API钩取

《逆向工程核心原理》学习笔记(四):API钩取

2024-07-18 04:07| 来源: 网络整理| 查看: 265

目录 前言一、API钩取简介1、基础概念2、技术图表 二、调试钩取技术1、调试器2、调试流程3、示例:记事本 WriteFile() API钩取(1)hookdbg.exe(2)试验 三、DLL注入实现IAT钩取技术1、选定目标API2、IAT钩取工作原理3、示例:计算器显示中文数字(1)hookiat.dll(2)InjectDll.exe 四、API代码修改技术1、API代码修改原理2、示例:隐藏进程(1)相关API(2)源码 五、全局API钩取1、相关API(1)Kernel32.CreateProcess()(2)Ntdll.ZwResumeThread() 2、源码(1)HideProc2.exe(2)stealth2.dll 结语

前言

继续学习《逆向工程核心原理》,本篇笔记是第四部分:API钩取,主要介绍了调试钩取、DLL注入实现IAT钩取、API代码修改钩取和全局API钩取等内容

一、API钩取简介 1、基础概念

钩取(Hook):截取信息、更改程序执行流向、添加新功能的技术

使用反汇编/调试器把握程序结构与原理开发Hook代码,以修改bug、改善程序功能灵活操作可执行文件和进程内存,设置Hook代码

API(Application Programming Interface):可以认为是调用资源的路径,notepad.exe为例如下图所示

在这里插入图片描述 其API调用如下: 在这里插入图片描述 API钩取:对Win32 API的钩取,一个例子如下图所示

在这里插入图片描述

2、技术图表

在这里插入图片描述 (下划线的是常用且好用的方法)

二、调试钩取技术

通过调试钩取技术,来钩取kernel32!WriteFile() API

1、调试器

调试器(Debbuger):能逐一执行被调试者的指令,拥有对寄存器和内存的所有访问权限,工作原理如下图所示

在这里插入图片描述 调试事件共9种,见微软官方调试事件 其中,与调试相关的是EXCEPTION_DEBUG_EVENT,与其相关的异常列表如下:

在这里插入图片描述 其中,调试器必须处理的是EXCEPTION_BREAKPOINT(断点),对应汇编指令是INT3,IA-32指令是0xCC 要设置断点时,只需将代码在内存中的起始地址的1个字节设置为0xCC即可,想继续调试就把它恢复

2、调试流程

基本思路:被调试者的API起始部份修改为0xCC,控制权转移到调试器后执行指定操作,最后使被调试者重新进入运行状态

对目标进程进行附加操作,使之成为被调试者Hook:API起始地址的第1个字节修改为0xCC调用相应API,控制权转移到调试器执行操作:操作参数、返回值等脱钩:0xCC恢复原值运行相应API(正常状态)Hook:再次修改为0xCC(继续钩取)控制权返还被调试者 3、示例:记事本 WriteFile() API钩取

目标是将notepad.exe中所有小写字母都变成大写字母

WriteFile() 定义如下:

BOOL WriteFile( HANDLE hFile, //文件句柄 LPCVOID lpBuffer, //数据缓存区指针 DWORD nNumberOfBytesToWrite, //要写的字节数 LPDWORD lpNumberOfBytesWritten, //用于保存实际写入字节数的存储区域的指针 LPOVERLAPPED lpOverlapped //OVERLAPPED结构体指针 ); (1)hookdbg.exe

源码如下:

// hookdbg.exe #include "windows.h" #include "stdio.h" LPVOID g_pfWriteFile = NULL; CREATE_PROCESS_DEBUG_INFO g_cpdi; BYTE g_chINT3 = 0xCC, g_chOrgByte = 0; BOOL OnCreateProcessDebugEvent(LPDEBUG_EVENT pde) { // 获取 WriteFile() API 地址(注意是调试进程的内存地址,不是被调试进程) g_pfWriteFile = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile"); // API Hook - WriteFile() // 更改第一个字节为 0xCC (INT 3) // (orginal byte 是g_chOrgByte备份) memcpy(&g_cpdi, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO)); ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile, &g_chOrgByte, sizeof(BYTE), NULL); WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, &g_chINT3, sizeof(BYTE), NULL); return TRUE; } BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pde) { CONTEXT ctx; PBYTE lpBuffer = NULL; DWORD dwNumOfBytesToWrite, dwAddrOfBuffer, i; PEXCEPTION_RECORD per = &pde->u.Exception.ExceptionRecord; // 断点异常 (INT 3) if( EXCEPTION_BREAKPOINT == per->ExceptionCode ) { // 断点地址为 WriteFile() API 地址 if( g_pfWriteFile == per->ExceptionAddress ) { // #1. Unhook // 0xCC 恢复为 original byte WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, &g_chOrgByte, sizeof(BYTE), NULL); // #2. 获取线程上下文 ctx.ContextFlags = CONTEXT_CONTROL; GetThreadContext(g_cpdi.hThread, &ctx); // #3. 获取 WriteFile() 的 param 2, 3 值 // 函数参数存在于相应进程的栈 // param 2 : ESP + 0x8 缓冲区地址 // param 3 : ESP + 0xC 缓冲区大小 ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0x8), &dwAddrOfBuffer, sizeof(DWORD), NULL); ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0xC), &dwNumOfBytesToWrite, sizeof(DWORD), NULL); // #4. 分配临时缓冲区 lpBuffer = (PBYTE)malloc(dwNumOfBytesToWrite+1); memset(lpBuffer, 0, dwNumOfBytesToWrite+1); // #5. 复制 WriteFile() 缓冲区到临时缓冲区 ReadProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer, lpBuffer, dwNumOfBytesToWrite, NULL); printf("\n### original string ###\n%s\n", lpBuffer); // #6. 小写字母 -> 大写字母 for( i = 0; i DEBUG_EVENT de; DWORD dwContinueStatus; // 等待被调试者发生事件 while( WaitForDebugEvent(&de, INFINITE) ) { dwContinueStatus = DBG_CONTINUE; //dwContinueStatus值为DBG_CONTINUE(处理正常)或DBG_EXCEPTION_NOT_HANDLED(无法处理或在SEH中处理) // 被调试者生成或附加事件 if( CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode ) { OnCreateProcessDebugEvent(&de); //OnCreateProcessDebugEvent是CREATE_PROCESS_DEBUG_EVENT事件句柄 } // 异常事件 else if( EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode ) { if( OnExceptionDebugEvent(&de) ) //OnExceptionDebugEvent是EXCEPTION_DEBUG_EVENT事件句柄,处理被调试者的INT3指令 continue; } // 被调试者终止事件 else if( EXIT_PROCESS_DEBUG_EVENT == de.dwDebugEventCode ) { // 被调试者终止 -> debugger 终止 break; } // 再次运行被调试者 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus); } } int main(int argc, char* argv[]) { DWORD dwPID; if( argc != 2 ) { printf("\nUSAGE : hookdbg.exe \n"); return 1; } // Attach Process dwPID = atoi(argv[1]); //以程序运行参数的形式接收进程PID if( !DebugActiveProcess(dwPID) ) //将调试器附加到进程上 { printf("DebugActiveProcess(%d) failed!!!\n" "Error Code = %d\n", dwPID, GetLastError()); return 1; } // 调试器循环 DebugLoop(); return 0; } (2)试验

先运行notepad.exe,并获取notepad的PID是32220,然后运行hookdbg.exe,如下 在这里插入图片描述 输入一串字符串,保存 再次打开的时候会发现都变成大写字母了

在这里插入图片描述

三、DLL注入实现IAT钩取技术

本节向计算器calc.exe插入用户的DLL文件,钩取IAT的user32.SetWindowTextW() API地址,使得计算器显示中文数字

1、选定目标API

PEView打开calc.exe,在IAT中寻找API,如下两个负责显示文本 在这里插入图片描述 其中,SetDigitemTextW()又调用了SetWindowTextW() SetWindowTextW() API定义如下:

BOOL SetWindowText( HWND hwnd, //窗口句柄 LPCTSTR lpString //字符串指针(钩取的目标) );

在OD里验证下 右键-search for-all intermodular calls,在SetWindowTextW()设置断点

在这里插入图片描述 运行,然后可以看到第一个断点处lpString的值是0,就是计算器显示的初始值

在这里插入图片描述 在计算器中输入7,继续运行,发现lpString的值变为7(注意此时地址不同)

在这里插入图片描述 尝试修改为中文“七”,Unicode码4e03,记住是小端序故要逆序 然后就会在计算器上显示“七” 验证完毕

2、IAT钩取工作原理

关于IAT,可以见《逆向工程核心原理》学习笔记(二):PE文件

原理如下图所示:

首先注入hookiat.dll文件,文件中提供了 MySetWindowTextW() 函数然后修改IAT中的CALL的值为 MySetWindowTextW() 函数起始地址一系列处理后,再CALL到user32.SetWindowTextW()函数起始地址user32.SetWindowTextW()执行完后返回到hookiat.dll执行下一条指令最后返回到01002628

在这里插入图片描述

3、示例:计算器显示中文数字 (1)hookiat.dll // hookiat.dll #include "stdio.h" #include "wchar.h" #include "windows.h" // typedef typedef BOOL (WINAPI *PFSETWINDOWTEXTW)(HWND hWnd, LPWSTR lpString); // globals FARPROC g_pOrgFunc = NULL; BOOL WINAPI MySetWindowTextW(HWND hWnd, LPWSTR lpString) { wchar_t* pNum = L"零一二三四五六七八九"; wchar_t temp[2] = {0,}; int i = 0, nLen = 0, nIndex = 0; nLen = wcslen(lpString); for(i = 0; i temp[0] = lpString[i]; nIndex = _wtoi(temp); lpString[i] = pNum[nIndex]; } } // 调用 user32!SetWindowTextW() API // (修改 lpString 缓冲区中内容) return ((PFSETWINDOWTEXTW)g_pOrgFunc)(hWnd, lpString); } // hook_iat // 负责钩取 IAT BOOL hook_iat(LPCSTR szDllName, PROC pfnOrg, PROC pfnNew) { HMODULE hMod; LPCSTR szLibName; PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_THUNK_DATA pThunk; DWORD dwOldProtect, dwRVA; PBYTE pAddr; //查找 IAT 位置 // hMod, pAddr = ImageBase of calc.exe // = VA to MZ signature (IMAGE_DOS_HEADER) hMod = GetModuleHandle(NULL); pAddr = (PBYTE)hMod; // pAddr = VA to PE signature (IMAGE_NT_HEADERS) pAddr += *((DWORD*)&pAddr[0x3C]); // dwRVA = RVA to IMAGE_IMPORT_DESCRIPTOR Table dwRVA = *((DWORD*)&pAddr[0x80]); // pImportDesc = VA to IMAGE_IMPORT_DESCRIPTOR Table pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hMod+dwRVA); // for循环找到user32.dll for( ; pImportDesc->Name; pImportDesc++ ) { // szLibName = VA to IMAGE_IMPORT_DESCRIPTOR.Name szLibName = (LPCSTR)((DWORD)hMod + pImportDesc->Name); if( !_stricmp(szLibName, szDllName) ) { // pThunk = IMAGE_IMPORT_DESCRIPTOR.FirstThunk // = VA to IAT(Import Address Table) pThunk = (PIMAGE_THUNK_DATA)((DWORD)hMod + pImportDesc->FirstThunk); // for循环找到SetWindowTextW的IAT地址 // pThunk->u1.Function = VA to API for( ; pThunk->u1.Function; pThunk++ ) { if( pThunk->u1.Function == (DWORD)pfnOrg ) { // 更改内存属性为 E/R/W VirtualProtect((LPVOID)&pThunk->u1.Function, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect); // 修改 IAT 值(钩取) pThunk->u1.Function = (DWORD)pfnNew; // 恢复内存属性 VirtualProtect((LPVOID)&pThunk->u1.Function, 4, dwOldProtect, &dwOldProtect); return TRUE; } } } } return FALSE; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch( fdwReason ) { case DLL_PROCESS_ATTACH : // 保存原始 API 地址 g_pOrgFunc = GetProcAddress(GetModuleHandle(L"user32.dll"), "SetWindowTextW"); // # hook // 用 hookiat.MySetWindowText() 钩取 user32.SetWindowTextW() hook_iat("user32.dll", g_pOrgFunc, (PROC)MySetWindowTextW); break; case DLL_PROCESS_DETACH : // # unhook // 将 calc.exe 的 IAT 恢复原值 hook_iat("user32.dll", (PROC)MySetWindowTextW, g_pOrgFunc); break; } return TRUE; } (2)InjectDll.exe

类似于《逆向工程核心原理》学习笔记(三):DLL注入

// InjectDll.exe #include "stdio.h" #include "windows.h" #include "tlhelp32.h" #include "winbase.h" #include "tchar.h" void usage() { printf("\nInjectDll.exe by ReverseCore\n" "- blog : http://www.reversecore.com\n" "- email : [email protected]\n\n" "- USAGE : InjectDll.exe \n\n"); } BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName) { HANDLE hProcess, hThread; LPVOID pRemoteBuf; DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR); LPTHREAD_START_ROUTINE pThreadProc; if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) { DWORD dwErr = GetLastError(); return FALSE; } pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess); return TRUE; } BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName) { BOOL bMore = FALSE, bFound = FALSE; HANDLE hSnapshot, hProcess, hThread; MODULEENTRY32 me = { sizeof(me) }; LPTHREAD_START_ROUTINE pThreadProc; if( INVALID_HANDLE_VALUE == (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) ) return FALSE; bMore = Module32First(hSnapshot, &me); for( ;bMore ;bMore = Module32Next(hSnapshot, &me) ) { if( !_tcsicmp(me.szModule, szDllName) || !_tcsicmp(me.szExePath, szDllName) ) { bFound = TRUE; break; } } if( !bFound ) { CloseHandle(hSnapshot); return FALSE; } if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) { CloseHandle(hSnapshot); return FALSE; } pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess); CloseHandle(hSnapshot); return TRUE; } DWORD _EnableNTPrivilege(LPCTSTR szPrivilege, DWORD dwState) { DWORD dwRtn = 0; HANDLE hToken; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { LUID luid; if (LookupPrivilegeValue(NULL, szPrivilege, &luid)) { BYTE t1[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)]; BYTE t2[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)]; DWORD cbTP = sizeof(TOKEN_PRIVILEGES) + sizeof (LUID_AND_ATTRIBUTES); PTOKEN_PRIVILEGES pTP = (PTOKEN_PRIVILEGES)t1; PTOKEN_PRIVILEGES pPrevTP = (PTOKEN_PRIVILEGES)t2; pTP->PrivilegeCount = 1; pTP->Privileges[0].Luid = luid; pTP->Privileges[0].Attributes = dwState; if (AdjustTokenPrivileges(hToken, FALSE, pTP, cbTP, pPrevTP, &cbTP)) dwRtn = pPrevTP->Privileges[0].Attributes; } CloseHandle(hToken); } return dwRtn; } int _tmain(int argc, TCHAR* argv[]) { if( argc != 4 ) { usage(); return 1; } // adjust privilege _EnableNTPrivilege(SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED); // InjectDll.exe if( !_tcsicmp(argv[1], L"i") ) InjectDll((DWORD)_tstoi(argv[2]), argv[3]); else if(!_tcsicmp(argv[1], L"e") ) EjectDll((DWORD)_tstoi(argv[2]), argv[3]); return 0; } 四、API代码修改技术

API代码修改技术:库文件被加载到进程内存后,在目录映像中直接修改要钩取的API代码本身(相较于上一节的IAT钩取,本技术可以钩取更多的不在IAT的API)

本节将用API代码修改技术实现隐藏进程

1、API代码修改原理

原始状态如下: 在这里插入图片描述

钩取原理如下图所示:

注入stealth.dll,钩取ntdll.ZwQuerySystemInformation() APIntdll.ZwQuerySystemInformation() API起始地址的5个字节代码改为stealth.MyZwQuerySystemInformation() 的地址JMP 10001120于是 ntdll.ZwQuerySystemInformation()被调用的时候,会跳转到stealth.MyZwQuerySystemInformation()1000116A的指令将 ntdll.ZwQuerySystemInformation() API起始地址的5个字节代码恢复原值1000119B的指令调用正常的 ntdll.ZwQuerySystemInformation()ntdll.ZwQuerySystemInformation()执行完后,返回stealth.dll然后10001212再次钩取ntdll.ZwQuerySystemInformation()(即第二步)stealth.MyZwQuerySystemInformation() 执行完后,返回进程

在这里插入图片描述

2、示例:隐藏进程 (1)相关API

一般获取进程快照,用的是CreateToolHelp32Snapshot() API 枚举进程则用的是EnumProcesses() API

而这两个API底层都调用的是 ntdll.ZwQuerySystemInformation() API ntdll.ZwQuerySystemInformation() API可以获取运行中的所有进程信息,形成链表

NTSTATUS WINAPI ZwQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Inout_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength );

隐藏进程时,需要钩取所有进程的ZwQuerySystemInformation() API,即全局钩取

(2)源码

HideProc.exe,可以认为是InjectDll.exe的加强版

// HideProc.exe #include "windows.h" #include "stdio.h" #include "tlhelp32.h" #include "tchar.h" typedef void (*PFN_SetProcName)(LPCTSTR szProcName); enum {INJECTION_MODE = 0, EJECTION_MODE}; BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { printf("OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid) ) // receives LUID of privilege { printf("LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { printf("The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath) { HANDLE hProcess, hThread; LPVOID pRemoteBuf; DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR); LPTHREAD_START_ROUTINE pThreadProc; if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) { printf("OpenProcess(%d) failed!!!\n", dwPID); return FALSE; } pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); pThreadProc = (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); WaitForSingleObject(hThread, INFINITE); VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); return TRUE; } BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath) { BOOL bMore = FALSE, bFound = FALSE; HANDLE hSnapshot, hProcess, hThread; MODULEENTRY32 me = { sizeof(me) }; LPTHREAD_START_ROUTINE pThreadProc; if( INVALID_HANDLE_VALUE == (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) ) return FALSE; bMore = Module32First(hSnapshot, &me); for( ; bMore ; bMore = Module32Next(hSnapshot, &me) ) { if( !_tcsicmp(me.szModule, szDllPath) || !_tcsicmp(me.szExePath, szDllPath) ) { bFound = TRUE; break; } } if( !bFound ) { CloseHandle(hSnapshot); return FALSE; } if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) { CloseHandle(hSnapshot); return FALSE; } pThreadProc = (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess); CloseHandle(hSnapshot); return TRUE; } BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath) { DWORD dwPID = 0; HANDLE hSnapShot = INVALID_HANDLE_VALUE; PROCESSENTRY32 pe; // Get the snapshot of the system pe.dwSize = sizeof( PROCESSENTRY32 ); hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL ); // find process Process32First(hSnapShot, &pe); do { dwPID = pe.th32ProcessID; if( dwPID printf("\n Usage : HideProc.exe "\ " \n\n"); return 1; } // change privilege SetPrivilege(SE_DEBUG_NAME, TRUE); // load library hLib = LoadLibrary(argv[3]); // set process name to hide SetProcName = (PFN_SetProcName)GetProcAddress(hLib, "SetProcName"); SetProcName(argv[2]); // Inject(Eject) Dll to all process if( !_tcsicmp(argv[1], L"-show") ) nMode = EJECTION_MODE; InjectAllProcess(nMode, argv[3]); // free library FreeLibrary(hLib); return 0; }

stealth.dll

// stealth.dll #include "windows.h" #include "tchar.h" #define STATUS_SUCCESS (0x00000000L) typedef LONG NTSTATUS; typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation = 0, SystemPerformanceInformation = 2, SystemTimeOfDayInformation = 3, SystemProcessInformation = 5, SystemProcessorPerformanceInformation = 8, SystemInterruptInformation = 23, SystemExceptionInformation = 33, SystemRegistryQuotaInformation = 37, SystemLookasideInformation = 45 } SYSTEM_INFORMATION_CLASS; typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfThreads; BYTE Reserved1[48]; PVOID Reserved2[3]; HANDLE UniqueProcessId; PVOID Reserved3; ULONG HandleCount; BYTE Reserved4[4]; PVOID Reserved5[11]; SIZE_T PeakPagefileUsage; SIZE_T PrivatePageCount; LARGE_INTEGER Reserved6[6]; } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION) (SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); #define DEF_NTDLL ("ntdll.dll") #define DEF_ZWQUERYSYSTEMINFORMATION ("ZwQuerySystemInformation") // global variable (in sharing memory) #pragma comment(linker, "/SECTION:.SHARE,RWS") #pragma data_seg(".SHARE") TCHAR g_szProcName[MAX_PATH] = {0,}; #pragma data_seg() // global variable BYTE g_pOrgBytes[5] = {0,}; //此函数用来将api前5个字节改为jmp xxxx,以实现钩取 //szDllName:dll名称,szFuncName:api名称,pfnNew:勾取函数地址,pOrgBytes:存储原来5个字节的缓冲区 BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes) { FARPROC pfnOrg; DWORD dwOldProtect, dwAddress; BYTE pBuf[5] = {0xE9, 0, }; PBYTE pByte; // 获取需要勾取的API地址 pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName); pByte = (PBYTE)pfnOrg; // 若已被勾取,则返回False if( pByte[0] == 0xE9 ) return FALSE; // 为了修改5字节,先向内存添加“写”的属性 VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); // 备份原有代码(5字节) memcpy(pOrgBytes, pfnOrg, 5); // 计算 JMP 地址 (E9 XXXX) // => XXXX = pfnNew - pfnOrg - 5 dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5; memcpy(&pBuf[1], &dwAddress, 4); // Hook - 修改 5 byte (JMP XXXX) memcpy(pfnOrg, pBuf, 5); // 恢复内存属性 VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect); return TRUE; } BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes) { FARPROC pFunc; DWORD dwOldProtect; PBYTE pByte; // 获取 API 地址 pFunc = GetProcAddress(GetModuleHandleA(szDllName), szFuncName); pByte = (PBYTE)pFunc; // 若已脱钩,则返回False if( pByte[0] != 0xE9 ) return FALSE; // 向内存添加“写”的属性,为恢复原代码做准备 VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); // Unhook memcpy(pFunc, pOrgBytes, 5); // 恢复内存属性 VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect); return TRUE; } // 勾取过程 NTSTATUS WINAPI NewZwQuerySystemInformation( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) { NTSTATUS status; FARPROC pFunc; PSYSTEM_PROCESS_INFORMATION pCur, pPrev; char szProcName[MAX_PATH] = {0,}; // 开始前先“脱钩” unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes); // 调用原始API pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL), DEF_ZWQUERYSYSTEMINFORMATION); status = ((PFZWQUERYSYSTEMINFORMATION)pFunc) (SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); if( status != STATUS_SUCCESS ) goto __NTQUERYSYSTEMINFORMATION_END; // 针对 SystemProcessInformation 类型操作 if( SystemInformationClass == SystemProcessInformation ) { // SYSTEM_PROCESS_INFORMATION 类型转换 // pCur 是单向链表的头 pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation; while(TRUE) { // 比较进程名称 // g_szProcName为要隐藏的进程的名称 // (=在SetProcName()设置) if(pCur->Reserved2[1] != NULL) { if(!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName)) { // 从链表中删除隐藏进程的节点 if(pCur->NextEntryOffset == 0) pPrev->NextEntryOffset = 0; else pPrev->NextEntryOffset += pCur->NextEntryOffset; } else pPrev = pCur; } if(pCur->NextEntryOffset == 0) break; // 链表的下一项 pCur = (PSYSTEM_PROCESS_INFORMATION) ((ULONG)pCur + pCur->NextEntryOffset); } } __NTQUERYSYSTEMINFORMATION_END: // 函数终止前,再次执行API勾取操作,为下次调用准备 hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, (PROC)NewZwQuerySystemInformation, g_pOrgBytes); return status; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { char szCurProc[MAX_PATH] = {0,}; char *p = NULL; // #1. 异常处理 // 若当前进程为 HookProc.exe 则不进行钩取 GetModuleFileNameA(NULL, szCurProc, MAX_PATH); p = strrchr(szCurProc, '\\'); if( (p != NULL) && !_stricmp(p+1, "HideProc.exe") ) return TRUE; switch( fdwReason ) { // #2. API Hooking case DLL_PROCESS_ATTACH : hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, (PROC)NewZwQuerySystemInformation, g_pOrgBytes); break; // #3. API Unhooking case DLL_PROCESS_DETACH : unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes); break; } return TRUE; } #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) void SetProcName(LPCTSTR szProcName) { _tcscpy_s(g_szProcName, szProcName); } #ifdef __cplusplus } #endif 五、全局API钩取

全局 API 钩取针对所有进程,包括正在运行和将要运行的进程 用全局API钩取对上一节内容进行加强

1、相关API (1)Kernel32.CreateProcess()

Kernel32.CreateProcess() API 是用来创建新进程的,钩取时要注意:

要同时钩取Kernel32.CreateProcessA()和Kernel32.CreateProcessW()上两个API分别调用了CreateProcessInternalA()和CreateProcessInternalW(),故这两个API也要钩取 BOOL CreateProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );

可参考CreateProcess函数详解

(2)Ntdll.ZwResumeThread()

Ntdll.ZwResumeThread()在进程创建后,主线程运行前在Kernel32.CreateProcess() 内被调用执行,不过这个API似乎并未公开,故有不确定性

ZwResumeThread( IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL ) 2、源码 (1)HideProc2.exe

HideProc2.exe与HideProc.exe相似

// HideProc2.exe #include "windows.h" #include "stdio.h" #include "tlhelp32.h" #include "tchar.h" enum {INJECTION_MODE = 0, EJECTION_MODE}; BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { printf("OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid) ) // receives LUID of privilege { printf("LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { printf("The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath) { HANDLE hProcess, hThread; LPVOID pRemoteBuf; DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR); LPTHREAD_START_ROUTINE pThreadProc; if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) { printf("OpenProcess(%d) failed!!!\n", dwPID); return FALSE; } pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); pThreadProc = (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); WaitForSingleObject(hThread, INFINITE); VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); return TRUE; } BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath) { BOOL bMore = FALSE, bFound = FALSE; HANDLE hSnapshot, hProcess, hThread; MODULEENTRY32 me = { sizeof(me) }; LPTHREAD_START_ROUTINE pThreadProc; if( INVALID_HANDLE_VALUE == (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) ) return FALSE; bMore = Module32First(hSnapshot, &me); for( ; bMore ; bMore = Module32Next(hSnapshot, &me) ) { if( !_tcsicmp(me.szModule, szDllPath) || !_tcsicmp(me.szExePath, szDllPath) ) { bFound = TRUE; break; } } if( !bFound ) { CloseHandle(hSnapshot); return FALSE; } if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) { printf("OpenProcess(%d) failed!!!\n", dwPID); CloseHandle(hSnapshot); return FALSE; } pThreadProc = (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess); CloseHandle(hSnapshot); return TRUE; } BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath) { DWORD dwPID = 0; HANDLE hSnapShot = INVALID_HANDLE_VALUE; PROCESSENTRY32 pe; // Get the snapshot of the system pe.dwSize = sizeof( PROCESSENTRY32 ); hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL ); // find process Process32First(hSnapShot, &pe); do { dwPID = pe.th32ProcessID; if( dwPID printf("\n Usage : HideProc2.exe \n\n"); return 1; } // change privilege SetPrivilege(SE_DEBUG_NAME, TRUE); // Inject(Eject) Dll to all process if( !_tcsicmp(argv[1], L"-show") ) nMode = EJECTION_MODE; InjectAllProcess(nMode, argv[2]); return 0; } (2)stealth2.dll

使用时先将stealth2.dll复制到%SYSTEM%文件夹

#include "windows.h" #include "stdio.h" #include "tchar.h" #define STR_MODULE_NAME (L"stealth2.dll") #define STR_HIDE_PROCESS_NAME (L"notepad.exe") #define STATUS_SUCCESS (0x00000000L) typedef LONG NTSTATUS; typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation = 0, SystemPerformanceInformation = 2, SystemTimeOfDayInformation = 3, SystemProcessInformation = 5, SystemProcessorPerformanceInformation = 8, SystemInterruptInformation = 23, SystemExceptionInformation = 33, SystemRegistryQuotaInformation = 37, SystemLookasideInformation = 45 } SYSTEM_INFORMATION_CLASS; typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; BYTE Reserved1[52]; PVOID Reserved2[3]; HANDLE UniqueProcessId; PVOID Reserved3; ULONG HandleCount; BYTE Reserved4[4]; PVOID Reserved5[11]; SIZE_T PeakPagefileUsage; SIZE_T PrivatePageCount; LARGE_INTEGER Reserved6[6]; } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); typedef BOOL (WINAPI *PFCREATEPROCESSA)( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); typedef BOOL (WINAPI *PFCREATEPROCESSW)( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); BYTE g_pOrgCPA[5] = {0,}; BYTE g_pOrgCPW[5] = {0,}; BYTE g_pOrgZwQSI[5] = {0,}; BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes) { FARPROC pFunc; DWORD dwOldProtect, dwAddress; BYTE pBuf[5] = {0xE9, 0, }; PBYTE pByte; pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName); pByte = (PBYTE)pFunc; if( pByte[0] == 0xE9 ) return FALSE; VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); memcpy(pOrgBytes, pFunc, 5); dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5; memcpy(&pBuf[1], &dwAddress, 4); memcpy(pFunc, pBuf, 5); VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect); return TRUE; } BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes) { FARPROC pFunc; DWORD dwOldProtect; PBYTE pByte; pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName); pByte = (PBYTE)pFunc; if( pByte[0] != 0xE9 ) return FALSE; VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); memcpy(pFunc, pOrgBytes, 5); VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect); return TRUE; } BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { printf("OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid) ) // receives LUID of privilege { printf("LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { printf("The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } // 这个InjectDll2值得注意下 BOOL InjectDll2(HANDLE hProcess, LPCTSTR szDllName) { HANDLE hThread; LPVOID pRemoteBuf; DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR); FARPROC pThreadProc; pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); if( pRemoteBuf == NULL ) return FALSE; WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL); pThreadProc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW"); hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pThreadProc, pRemoteBuf, 0, NULL); WaitForSingleObject(hThread, INFINITE); VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE); CloseHandle(hThread); return TRUE; } NTSTATUS WINAPI NewZwQuerySystemInformation( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) { NTSTATUS status; FARPROC pFunc; PSYSTEM_PROCESS_INFORMATION pCur, pPrev; char szProcName[MAX_PATH] = {0,}; unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", g_pOrgZwQSI); pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQuerySystemInformation"); status = ((PFZWQUERYSYSTEMINFORMATION)pFunc) (SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); if( status != STATUS_SUCCESS ) goto __NTQUERYSYSTEMINFORMATION_END; if( SystemInformationClass == SystemProcessInformation ) { pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation; while(TRUE) { if(pCur->Reserved2[1] != NULL) { if(!_tcsicmp((PWSTR)pCur->Reserved2[1], STR_HIDE_PROCESS_NAME)) { if(pCur->NextEntryOffset == 0) pPrev->NextEntryOffset = 0; else pPrev->NextEntryOffset += pCur->NextEntryOffset; } else pPrev = pCur; } if(pCur->NextEntryOffset == 0) break; pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset); } } __NTQUERYSYSTEMINFORMATION_END: hook_by_code("ntdll.dll", "ZwQuerySystemInformation", (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI); return status; } BOOL WINAPI NewCreateProcessA( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ) { BOOL bRet; FARPROC pFunc; // unhook unhook_by_code("kernel32.dll", "CreateProcessA", g_pOrgCPA); // 调用 original API pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA"); bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); // 向生成的子进程注入stealth2.dll if( bRet ) InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME); // hook hook_by_code("kernel32.dll", "CreateProcessA", (PROC)NewCreateProcessA, g_pOrgCPA); return bRet; } BOOL WINAPI NewCreateProcessW( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ) { BOOL bRet; FARPROC pFunc; // unhook unhook_by_code("kernel32.dll", "CreateProcessW", g_pOrgCPW); // 调用 original API pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessW"); bRet = ((PFCREATEPROCESSW)pFunc)(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); // 向生成的子进程注入 stealth2.dll if( bRet ) InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME); // hook hook_by_code("kernel32.dll", "CreateProcessW", (PROC)NewCreateProcessW, g_pOrgCPW); return bRet; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { char szCurProc[MAX_PATH] = {0,}; char *p = NULL; // 异常处理使注入不会发生在 HideProc2.exe 进程 GetModuleFileNameA(NULL, szCurProc, MAX_PATH); p = strrchr(szCurProc, '\\'); if( (p != NULL) && !_stricmp(p+1, "HideProc2.exe") ) return TRUE; // change privilege SetPrivilege(SE_DEBUG_NAME, TRUE); switch( fdwReason ) { case DLL_PROCESS_ATTACH : // hook hook_by_code("kernel32.dll", "CreateProcessA", (PROC)NewCreateProcessA, g_pOrgCPA); hook_by_code("kernel32.dll", "CreateProcessW", (PROC)NewCreateProcessW, g_pOrgCPW); hook_by_code("ntdll.dll", "ZwQuerySystemInformation", (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI); break; case DLL_PROCESS_DETACH : // unhook unhook_by_code("kernel32.dll", "CreateProcessA", g_pOrgCPA); unhook_by_code("kernel32.dll", "CreateProcessW", g_pOrgCPW); unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", g_pOrgZwQSI); break; } return TRUE; } 结语

本章对API钩取做了学习 书中还提点了下工具的使用标准



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有